const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g //匹配花括号 {{  }} 捕获花括号里面的内容

const ELEMENT_TYPE = 1

function gen(node) {
  // 判断节点类型
  // 主要包含处理文本核心
  // 源码这块包含了复杂的处理  比如 v-once v-for v-if 自定义指令 slot等等  咱们这里只考虑普通文本和变量表达式{{}}的处理

  // 如果是元素节点
  if (node.type === ELEMENT_TYPE) {
    // 递归创建
    return generate(node)
  } else {
    // 如果是文本节点
    let text = node.text
    // 不存在花括号变量表达式
    if (!defaultTagRE.test(text)) {
      return `_v(${JSON.stringify(text)})`
    }

    // 正则是全局模式 每次需要重置正则的lastIndex属性  不然会引发匹配bug
    let lastIndex = (defaultTagRE.lastIndex = 0)
    let tokens = []
    let match, index

    while ((match = defaultTagRE.exec(text))) {
      // index 代表匹配到的位置
      index = match.index

      if (index > lastIndex) {
        // 匹配到的{{位置  在tokens里面放入普通文本
        tokens.push(JSON.stringify(text.slice(lastIndex, index)))
      }

      // 放入捕获到的变量内容
      tokens.push(`_s(${match[1].trim()})`)

      // 匹配指针后移
      lastIndex = index + match[0].length
    }

    // 如果匹配完了花括号  text里面还有剩余的普通文本 那么继续push
    if (lastIndex < text.length) {
      tokens.push(JSON.stringify(text.slice(lastIndex)))
    }
    // _v表示创建文本
    return `_v(${tokens.join('+')})`
  }
}

// 处理 attrs 属性
function genProps(attrs) {
  let str = ''
  for (let i = 0; i < attrs.length; i++) {
    let attr = attrs[i]
    if (attr.name === 'style') {
      let obj = {}
      attr.value.split(';').forEach((item) => {
        let [key, value] = item.split(':')
        obj[key] = value
      })
      attr.value = obj
    }
    str += `${attr.name}:${JSON.stringify(attr.value)},`
  }
  return `{${str.slice(0, -1)}}`
}

// 生成子节点 调用gen函数进行递归创建
function getChildren(el) {
  const children = el.children
  if (children) {
    return `${children.map((c) => gen(c)).join(',')}`
  }
}

// ast => 代码
export function generate(el) {
  let children = getChildren(el)
  let code = `_c('${el.tag}',${
    el.attrs.length ? `${genProps(el.attrs)}` : 'undefined'
  }${children ? `,${children}` : ''})`
  return code
}
